package com.sktk.keepAccount.common.core.vo;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.sktk.keepAccount.common.core.exception.BaseException;
import com.sktk.keepAccount.common.core.exception.ErrorType;
import com.sktk.keepAccount.common.core.exception.SystemErrorType;
import com.sktk.keepAccount.common.core.util.AESUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Getter
public class Result<T> {

    public static final String SUCCESSFUL_CODE = "200";
    public static final String SUCCESSFUL_MSG = "操作成功";
    public static final String SALT = "QV3KOjKoPhT8qTtt";

    private String code;
    private String msg;
    private Long time;
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private T data;

    private static String env;

    public static void setEnv(String env) {
        Result.env = env;
    }

    public static String getEnv() {
        return Result.env;
    }

    public Result() {
        this.time = System.currentTimeMillis();
    }

    /**
     * @param errorType
     */
    public Result(ErrorType errorType) {
        this.code = errorType.getCode();
        this.msg = errorType.getMsg();
        this.time = System.currentTimeMillis();
    }

    /**
     * @param errorType
     * @param data
     */
    public Result(ErrorType errorType, T data) {
        this(errorType);
        this.data = data;
    }

    public Result(ErrorType errorType, String extra) {
        this(errorType);
        this.msg = errorType.getMsg() + extra;
    }

    /**
     * 内部使用，用于构造成功的结果
     *
     * @param code
     * @param msg
     * @param data
     */
    private Result(String code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.time = System.currentTimeMillis();
    }

    /**
     * 快速创建成功结果并返回结果数据
     *
     * @param data
     * @return Result
     */
    public static String success(Object data) {
        if (env.equals("dev")) {
            return JSONObject.toJSONString(
                    new Result<>(SUCCESSFUL_CODE, SUCCESSFUL_MSG, data));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result<>(SUCCESSFUL_CODE, SUCCESSFUL_MSG, data)), SALT);
    }

    /**
     * 快速创建成功结果
     *
     * @return Result
     */
    public static String success() {
        return success(null);
    }

    /**
     * 系统异常类没有返回数据
     *
     * @return Result
     */
    public static String fail() {
        if (Result.getEnv().equals("dev")) {
            return JSONObject.toJSONString(
                    new Result(SystemErrorType.SYSTEM_ERROR));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result(SystemErrorType.SYSTEM_ERROR)), SALT);
    }

    /**
     * 系统异常类没有返回数据
     *
     * @param baseException
     * @return Result
     */
    public static String fail(BaseException baseException) {
        return fail(baseException, SALT);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param data
     * @return Result
     */
    public static String fail(BaseException baseException, Object data) {
        if (env.equals("dev")) {
            return JSONObject.toJSONString(
                    new Result<>(baseException.getErrorType(), data));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result<>(baseException.getErrorType(), data)), SALT);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param errorType
     * @param data
     * @return Result
     */
    public static String fail(ErrorType errorType, Object data) {
        if (env.equals("dev")) {
            return JSONObject.toJSONString(
                    new Result<>(errorType, data));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result<>(errorType, data)), SALT);
    }

    public static String fail(ErrorType errorType, String extra) {
        if (env.equals("dev")) {
            return JSONObject.toJSONString(
                    new Result<>(errorType, extra));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result<>(errorType, extra)), SALT);
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param errorType
     * @return Result
     */
    public static String fail(ErrorType errorType) {
        log.error("异常返回 error code:{} msg:{}", errorType.getCode(), errorType.getMsg());
        return Result.fail(errorType, new Object());
    }

    /**
     * 系统异常类并返回结果数据
     *
     * @param data
     * @return Result
     */
    public static String fail(Object data) {
        if (env.equals("dev")) {
            return JSONObject.toJSONString(
                    new Result<>(SystemErrorType.SYSTEM_ERROR, data));
        }
        return AESUtil.encrypt(JSONObject.toJSONString(
                new Result<>(SystemErrorType.SYSTEM_ERROR, data)), SALT);
    }


    /**
     * 成功code=000000
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESSFUL_CODE.equals(this.code);
    }

    /**
     * 失败
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }
}
